package com.soujiayi.activity;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Date;

import org.json.JSONArray;
import org.json.JSONObject;
import org.xmlpull.v1.XmlPullParser;

import com.soujiayi.model.UpdateInfo;
import com.soujiayi.net.HttpRequester;
import com.soujiayi.util.Constants;

import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;

import android.util.Log;
import android.util.Xml;

public class UpdateManager {

	private String curVersionName;
	private String newVersionName;
	private int curVersionCode;
	private int newVersionCode;
	private String updateDesc;
	private String apkUrl;
	private String size;
	private UpdateCallback callback;
	private Context ctx;

	private int progress;
	private Boolean hasNewVersion;
	private Boolean canceled;
	public static final String UPDATE_SAVENAME = "soujiayi.apk";
	
	private static final int UPDATE_CHECKCOMPLETED = 1;
	private static final int UPDATE_DOWNLOADING = 2;
	private static final int UPDATE_DOWNLOAD_ERROR = 3;
	private static final int UPDATE_DOWNLOAD_COMPLETED = 4;
	private static final int UPDATE_DOWNLOAD_CANCELED = 5;

	private String savefolder;

	public UpdateManager(Context context, UpdateCallback updateCallback) {
		ctx = context;
		callback = updateCallback;
		canceled = false;
		getCurVersion();
	}

	private void initDir() {
		if (Environment.getExternalStorageState().equals(
				Environment.MEDIA_MOUNTED))
			savefolder = Environment.getExternalStorageDirectory() + "/"
					+ Constants.STORAGECARD_DIR;
		else
			savefolder = ctx.getCacheDir().getAbsolutePath();
	}

	private void getCurVersion() {
		try {
			PackageInfo pInfo = ctx.getPackageManager().getPackageInfo(
					ctx.getPackageName(), 0);
			curVersionName = pInfo.versionName;
			curVersionCode = pInfo.versionCode;
		} catch (NameNotFoundException e) {
			Log.e("update", e.getMessage());
			curVersionName = "1.0.0";
			curVersionCode = 1;
		}

	}

	public void checkUpdate() {
		hasNewVersion = false;
		new Thread() {
			@Override
			public void run() {
				long start = new Date().getTime();	
				try {	
					URL url = new URL(Constants.UPDATE_CHECKURL);
					HttpURLConnection conn = (HttpURLConnection) url
							.openConnection();
					conn.setConnectTimeout(5000);
					InputStream is = conn.getInputStream();
					XmlPullParser parser = Xml.newPullParser();

					parser.setInput(is, "utf-8");
					int type = parser.getEventType();
					while (type != XmlPullParser.END_DOCUMENT) {
						switch (type) {
						case XmlPullParser.START_TAG:
							if ("verCode".equals(parser.getName())) {
								newVersionCode = Integer.parseInt(parser
										.nextText());
							} else if ("verName".equals(parser.getName())) {
								newVersionName = parser.nextText();
							} else if ("apkUrl".equals(parser.getName())) {
								apkUrl = parser.nextText();
							} else if ("desc".equals(parser.getName())) {
								updateDesc = parser.nextText();
							}else if ("size".equals(parser.getName())) {
								size = parser.nextText();
							}
							break;
						}
						type = parser.next();

					}
					if (newVersionCode > curVersionCode) {
						hasNewVersion = true;
					}

				} catch (Exception e) {
					Log.e("update", e.getMessage());
					newVersionCode = -1;
					newVersionName = "";
					updateDesc = "";
					apkUrl = "";
				}
				long end = new Date().getTime();		
				if(end - start <2000)
					updateHandler.sendEmptyMessageDelayed(UPDATE_CHECKCOMPLETED,2000);
				else
					updateHandler.sendEmptyMessage(UPDATE_CHECKCOMPLETED);
			};
		}.start();

	}

	public void update() {
		Intent intent = new Intent(Intent.ACTION_VIEW);
		intent.setDataAndType(
				Uri.fromFile(new File(savefolder, UPDATE_SAVENAME)),
				"application/vnd.android.package-archive");
		ctx.startActivity(intent);
	}

	public void downloadPackage() {

		new Thread() {
			@Override
			public void run() {
				try {
					initDir();
					URL url = new URL(apkUrl);
					HttpURLConnection conn = (HttpURLConnection) url
							.openConnection();
					conn.connect();
					int length = conn.getContentLength();
					InputStream is = conn.getInputStream();
					File ApkFile = new File(savefolder, UPDATE_SAVENAME);
					if (ApkFile.exists()) {
						ApkFile.delete();
					}

					FileOutputStream fos = new FileOutputStream(ApkFile);

					int count = 0;
					byte buf[] = new byte[512];

					do {

						int numread = is.read(buf);
						count += numread;
						progress = (int) (((float) count / length) * 100);
						updateHandler.sendMessage(updateHandler
								.obtainMessage(UPDATE_DOWNLOADING));
						if (numread <= 0) {
							updateHandler
									.sendEmptyMessage(UPDATE_DOWNLOAD_COMPLETED);
							break;
						}
						fos.write(buf, 0, numread);
					} while (!canceled);
					if (canceled) {
						updateHandler
								.sendEmptyMessage(UPDATE_DOWNLOAD_CANCELED);
					}
					fos.close();
					is.close();
				} catch (MalformedURLException e) {
					e.printStackTrace();

					updateHandler.sendMessage(updateHandler.obtainMessage(
							UPDATE_DOWNLOAD_ERROR, e.getMessage()));
				} catch (IOException e) {
					e.printStackTrace();

					updateHandler.sendMessage(updateHandler.obtainMessage(
							UPDATE_DOWNLOAD_ERROR, e.getMessage()));
				}

			}
		}.start();
	}

	public void cancelDownload() {
		canceled = true;
	}

	Handler updateHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {

			switch (msg.what) {
			case UPDATE_CHECKCOMPLETED:
				UpdateInfo updateInfo = new UpdateInfo();
				updateInfo.setVerName(newVersionName);
				updateInfo.setVerCode(newVersionCode);
				updateInfo.setApkUrl(apkUrl);
				updateInfo.setDesc(updateDesc);
				updateInfo.setSize(size);
				callback.checkUpdateCompleted(hasNewVersion, updateInfo);
				break;
			case UPDATE_DOWNLOADING:

				callback.downloadProgressChanged(progress);
				break;
			case UPDATE_DOWNLOAD_ERROR:

				callback.downloadCompleted(false, msg.obj.toString());
				break;
			case UPDATE_DOWNLOAD_COMPLETED:

				callback.downloadCompleted(true, "");
				break;
			case UPDATE_DOWNLOAD_CANCELED:

				callback.downloadCanceled();
			default:
				break;
			}
		}
	};

	public interface UpdateCallback {
		public void checkUpdateCompleted(Boolean hasUpdate,
				UpdateInfo updateInfo);

		public void downloadProgressChanged(int progress);

		public void downloadCanceled();

		public void downloadCompleted(Boolean sucess, CharSequence errorMsg);
	}

}